﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.IO;
using ConferenceZoom.Tests.DTDBService;
using IndicoInterface;
using ConferenceZoom.Controllers;
using System.Web.Mvc;
using ConferenceZoom.Tests.DTRender;
using System.Threading;
using System.ServiceModel;

namespace ConferenceZoom.Tests.Controllers
{
    /// <summary>
    /// Summary description for ConferenceControllerTest
    /// </summary>
    [TestClass]
    public class ConferenceControllerTest
    {
        public TestContext TestContext { get; set; }

        #region TestSetup
        [TestInitialize]
        public void InitTest()
        {
            FileInfo db = new FileInfo("ConfData_" + TestContext.TestName + ".sdf");
            File.Copy(@"..\..\..\DeepTalkDBService\ConferenceData.sdf", db.FullName);
            using (DTDBClient rc = new DTDBClient())
            {
                rc.SetDBFile(db);
            }
        }

        string GetTalkXML(string id)
        {
            /// Submit a talk for rendering -- should not crash! :-)

            AgendaInfo info = new AgendaInfo("http://indico.cern.ch/conferenceDisplay.py?showSession=all&showDate=all&view=xml&fr=no&confId=" + id);
            StringWriter sr = new StringWriter();
            info.Seralize(sr);
            return sr.ToString();
        }

        string GetTalkXML()
        {
            return GetTalkXML("a042880");
        }

        #endregion

        [TestMethod]
        public void TestRender()
        {
            ConferenceController cc = new ConferenceController();

            RedirectToRouteResult result = cc.Render("http://indico.cern.ch/conferenceDisplay.py?confId=14475") as RedirectToRouteResult;
            Assert.IsNotNull(result, "Redirect result expected");
            Assert.AreEqual("Show", result.RouteValues["action"], "Should be redirecting to the show page!");

            using (DTDBClient db = new DTDBClient())
            {
                BasicTalkInfo[] talks = db.GetUnrenderedTalks(10);
                Assert.AreEqual((int)1, talks.Length);
            }
        }

        [TestMethod]
        public void TestBadRenderURL()
        {
            ConferenceController cc = new ConferenceController();

            ViewResult result = cc.Render("http://nytimes.com") as ViewResult;
            Assert.IsNotNull(result, "View result expected");
            Assert.AreEqual("BadURLToRender", result.ViewName, "Should be redirecting to a bad URL page!");

            using (DTDBClient db = new DTDBClient())
            {
                BasicTalkInfo[] talks = db.GetUnrenderedTalks(10);
                Assert.AreEqual((int)0, talks.Length);
            }
        }

        [TestMethod]
        public void TestRenderedURL()
        {
            string url = "http://indico.cern.ch/conferenceDisplay.py?showSession=all&showDate=all&view=xml&fr=no&confId=123";

            using (DTDBClient db = new DTDBClient())
            {
                db.SubmitNewTalk(GetTalkXML("123"), "Talk 1", DateTime.Now);
            }
            cbrender cb = new cbrender();
            using (DTRenderClient rc = new DTRenderClient(new InstanceContext(cb)))
            {
                cb.Render = rc;
                rc.ReadyForWork();
                cb.Wait();
            }

            using (ConferenceController cc = new ConferenceController())
            {
                RedirectToRouteResult result = cc.Render(url) as RedirectToRouteResult;
                Assert.IsNotNull(result, "Redirect result expected");
                Assert.AreEqual("Show", result.RouteValues["action"], "Valid URL - should go to show!");
            }
        }

        [TestMethod]
        public void TestShowUnknownURL()
        {
            ConferenceController cc = new ConferenceController();

            RedirectToRouteResult result = cc.Show("http://indico.cern.ch/conferenceDisplay.py?confId=14475", null) as RedirectToRouteResult;
            Assert.IsNotNull(result, "Redirect result expected");
            Assert.AreEqual("Render", result.RouteValues["action"], "Should be redirecting to the Render page!");
        }

        [TestMethod]
        public void TestShowBADURL()
        {
            ConferenceController cc = new ConferenceController();

            ViewResult result = cc.Show("http://www.nytimes.com", null) as ViewResult;
            Assert.IsNotNull(result, "View result expected");
            Assert.AreEqual("BadURLToShow", result.ViewName, "Page to show bad url expected!");
        }

        [TestMethod]
        public void TestShowBadID()
        {
            ConferenceController cc = new ConferenceController();

            ViewResult result = cc.Show(null, 500) as ViewResult;
            Assert.IsNotNull(result, "View result expected");
            Assert.AreEqual("BadIDToShow", result.ViewName, "Expected bad ID show");
        }

        [TestMethod]
        public void TestShowPendingID()
        {
            using (DTDBClient db = new DTDBClient())
            {
                db.SubmitNewTalk(GetTalkXML("123"), "Talk 1", DateTime.Now);
            }
            using (ConferenceController cc = new ConferenceController())
            {
                ViewResult result = cc.Show(null, 1) as ViewResult;
                Assert.IsNotNull(result, "View result expected");
                Assert.AreEqual("ShowConferencePending", result.ViewName, "We are going to be showing a pending conference!");
            }
        }

        [TestMethod]
        public void TestShowPendingURL()
        {
            string url = "http://indico.cern.ch/conferenceDisplay.py?showSession=all&showDate=all&view=xml&fr=no&confId=123";

            using (DTDBClient db = new DTDBClient())
            {
                db.SubmitNewTalk(GetTalkXML("123"), "Talk 1", DateTime.Now);
            }
            using (ConferenceController cc = new ConferenceController())
            {
                ViewResult result = cc.Show(url, null) as ViewResult;
                Assert.IsNotNull(result, "View result expected");
                Assert.AreEqual("ShowConferencePending", result.ViewName, "We are going to be showing a pending conference!");
            }
        }

        class cbrender : DTRender.IDTRenderCallback
        {
            public DTRenderClient Render { get; set; }
            private AutoResetEvent evt = new AutoResetEvent(false);
            public void Wait()
            {
                evt.WaitOne();
            }

            public bool RenderTalk(ConferenceZoom.Tests.DTRender.DTRenderTalkInfo info)
            {
                ThreadPool.QueueUserWorkItem(o =>
                {
                    Thread.Sleep(100);
                    Render.RenderDone(info.ID, (float)100);
                    evt.Set();
                });
                return true;
            }
        }

        [TestMethod]
        public void TestShowRenderedURL()
        {
            string url = "http://indico.cern.ch/conferenceDisplay.py?showSession=all&showDate=all&view=xml&fr=no&confId=123";

            using (DTDBClient db = new DTDBClient())
            {
                db.SubmitNewTalk(GetTalkXML("123"), "Talk 1", DateTime.Now);
            }
            cbrender cb = new cbrender();
            using (DTRenderClient rc = new DTRenderClient(new InstanceContext(cb)))
            {
                cb.Render = rc;
                rc.ReadyForWork();
                cb.Wait();
            }

            using (ConferenceController cc = new ConferenceController())
            {
                ViewResult result = cc.Show(url, null) as ViewResult;
                Assert.IsNotNull(result, "View result expected");
                Assert.AreEqual("ShowConference", result.ViewName, "We are going to be showing a pending conference!");
            }
        }
    }
}
